﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using System.Diagnostics; 
using Microsoft.SharePoint;
using System.Runtime.InteropServices;


namespace AzureConnect
{
    public class Log
    {

        #region Components No Longer Needed
		////trace components so we don't have to keep recreating them
		//private static SPDiagnosticsCategory category = null;
		//private static SPDiagnosticsService ds = null;
        #endregion

        private const string LOG_CATEGORY = "AzureConnect";
        public const int LOG_ID = 10168;

        //determines level of logging
        public enum LogTypes
        {
            EventLog,
            UlsLog,
            Both
        }


        //private constructor since it is a static class   
        static Log()
        {
            try
            {
                //initialize tracing components; not needed since changed diagnostics class
                #region Old Constructor
				//category = new
				//    SPDiagnosticsCategory(LOG_CATEGORY, TraceSeverity.Medium,
				//    EventSeverity.Information);
				//ds = SPDiagnosticsService.Local;
                #endregion
            }
            catch (Exception ex)
            {
                //since this writes to the logs, if it fails there's no where really to write
                Debug.WriteLine(ex.Message);
            }
        }


        public static void WriteLog(string Message, LogTypes LogType, 
            TraceSeverity TraceLogSeverity, EventSeverity EventLogSeverity)
        {
            //write out the message to the appropriate log(s)
            try
            {
                //ULS log
                if ((LogType == LogTypes.Both) || (LogType == LogTypes.UlsLog))
					AzureConnectDiagnosticsService.Local.LogMessage(LOG_ID,
					    AzureConnectDiagnosticsService.LogCategories.AzureConfig,
					    TraceLogSeverity, Message, null);

                //no longer used since switched to custom diagnostic provider
					//ds.WriteTrace(LOG_ID, category, TraceLogSeverity, Message, null);

                //event log - separate try block since it will throw if the log is full
                try
                {
                    EventLogEntryType eType = EventLogEntryType.Information;

                    //convert from SharePoint log type to event log type
                    switch (EventLogSeverity)
                    {
                        case (EventSeverity.Error):
                        case (EventSeverity.ErrorCritical):
                            eType = EventLogEntryType.Error;
                            break;
                        case (EventSeverity.Information):
                            eType = EventLogEntryType.Information;
                            break;
                        case (EventSeverity.Verbose):
                            eType = EventLogEntryType.SuccessAudit;
                            break;
                        case (EventSeverity.Warning):
                            eType = EventLogEntryType.Warning;
                            break;
                    }

                    if ((LogType == LogTypes.Both) || (LogType == LogTypes.EventLog))
                        EventLog.WriteEntry(LOG_CATEGORY, Message, eType, LOG_ID);
                }
                catch
                {
                    //ignore at this point
                }
            }
            catch (Exception writeEx)
            {
                //ignore
                Debug.WriteLine(writeEx.Message);
            }
        }
    }


    [Guid("833B687D-0DD1-4F17-BF6A-B64FBC1AC6A8")]
	public class AzureConnectDiagnosticsService : SPDiagnosticsServiceBase
    {

        private const string LOG_AREA = "Azure Connect";
        private const string LOG_CATEGORY = "Azure Configuration";

        public enum LogCategories
        {
            AzureConfig
        }   


        public AzureConnectDiagnosticsService()
        {
        }  


        public AzureConnectDiagnosticsService(string name, SPFarm parent)
            : base(name, parent)
        {
        }  


		//protected override bool HasAdditionalUpdateAccess()
		//{
		//    // Without this SPDiagnosticsServiceBase.GetLocal<MyDiagnosticsService>()  
		//    // throws a SecurityException, see  
		//    // http://share2010.wordpress.com/tag/sppersistedobject/  
		//    return true;
		//} 


        public static AzureConnectDiagnosticsService Local
        {
            get
            {
                //may need to implement if ever used in a feature
                #region Feature Activated Fixes
                //// SPUtility.ValidateFormDigest(); doesn't work here  
                //if (SPContext.Current != null)
                //{
                //    SPContext.Current.Web.AllowUnsafeUpdates = true;
                //}
                //// (Else assume this is called from a FeatureReceiver)  
                #endregion

                return SPDiagnosticsServiceBase.GetLocal<AzureConnectDiagnosticsService>();
            }
        }


		public void LogMessage(ushort id, LogCategories LogCategory, TraceSeverity traceSeverity,
			string message, params object[] data)
		{

			if (traceSeverity != TraceSeverity.None)
			{

				// traceSeverity==TraceSeverity.None would cause an ArgumentException:  
				// "Specified value is not supported for the severity parameter."  

				SPDiagnosticsCategory category
					= Local.Areas[LOG_AREA].Categories[LogCategory.ToString()];
				Local.WriteTrace(id, category, traceSeverity, message, data);
			}

		} 


        protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
		{

			#region Old Method
			//List<SPDiagnosticsCategory> categories = new List<SPDiagnosticsCategory>();

			//categories.Add(new SPDiagnosticsCategory(
			// LogCategories.AzureConfig.ToString(),
			// TraceSeverity.Medium, EventSeverity.Information));

			//SPDiagnosticsArea area = new SPDiagnosticsArea(
			// LOG_AREA, 0, 0, false, categories);

			//List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>();

			//areas.Add(area);

			//return areas;
			#endregion

			yield return new SPDiagnosticsArea(LOG_AREA, 0, 0, false,
				new List<SPDiagnosticsCategory>()
                {
					new SPDiagnosticsCategory(LogCategories.AzureConfig.ToString(), 
						TraceSeverity.Medium, EventSeverity.Information, 1, 
						Log.LOG_ID)
					//new SPDiagnosticsCategory("Category 2", TraceSeverity.Verbose, EventSeverity.Verbose, 0, 0, false),
					//new SPDiagnosticsCategory("Category 3", TraceSeverity.Verbose, EventSeverity.Verbose, 0, 0, false),
                }
			);

        } 
    } 
}
